/**
 * El proceso DMon se encarga de monitorizar la acción de los
 * procesos DRep, llevar un registro de las conecciones y
 * los clientes dcli conectados a cualquier proceso DRep.
 * Los procesos DMon usan su propio protocolo, definido en
 * ProtocoloDMon.
 *
 * @author Colmenares Carlos (06-39380)
 * @author Tough Alex (07-41604)
 */
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

class DMon {

    public static void main(String[] args){
        //Primero se deben parsear los argumentos,
        //los siguientes son valores de default para
        //estos:
        int puertoDmon = 0;
        boolean verboso = false;

        try {

            int i = 0;
            while( i < args.length ){

                if( args[i].equals("-p") && i+1<args.length ){
                    puertoDmon = Integer.parseInt(args[++i]);
                }
                else if( args[i].equals("-v") ){
                    verboso = true;
                }
                else { //( args[i].equals("--help") )
                    imprimirUso();
                }
                i++;
            }
            if( puertoDmon == 0 )
                imprimirUso();
            if(puertoDmon > 65535){
                System.out.println("Error, especifique un número de puerto"+
                        "válido");
                System.exit(-1);
            }
        }
        catch(NumberFormatException nfe){
            System.err.println("Error obteniendo número de puertos, por "+
                    "favor indique números enteros");
            System.exit(1);
        }

        //Abrir el socket y esperar por conexiones
        ServerSocket socketServidor = null;

        System.out.println("Iniciando la conexión del servidor dmon, "+
                "esto puede tomar unos segundos...");

        try {
            socketServidor = new ServerSocket(puertoDmon);
        } catch (IOException e) {
            System.err.println("Error, no se pudo abrir el socket "
                    +puertoDmon);
            System.err.println(e);
            System.exit(-1);
        }

        //Crear las estructuras para tener control de los usuarios conectados 
        //y el número de operaciones realizadas
        Set<String> registroDeUsuarios =
            Collections.synchronizedSet(new HashSet<String>());

        Map<String,Set<String> > registroDeDRep =
            Collections.synchronizedMap(new HashMap<String,Set<String> >());

        int logDMon[] = new int[2];
        logDMon[0] = 0; //Número de uploads
        logDMon[1] = 0; //Número de downloads

        //Crear el thread principal para atender al creador de este proceso
        //por la consola
        new HiloDMon(registroDeUsuarios, registroDeDRep, logDMon,verboso).start();

        //Esperar por conexiones de clientes, al recibirlas,
        //crear un hilo que las atienda y seguir esperando
        //conexiones
        try {

            while(true){

                Socket socketCliente = null;
                socketCliente = socketServidor.accept();

                new HiloDMon(socketCliente, registroDeUsuarios, registroDeDRep, logDMon,verboso).start();
            }

        } catch (IOException e) {
            System.err.println("Error aceptando conexiones");
            System.err.println(e);
            System.exit(1);
        } finally{
            try{
                socketServidor.close();
            }
            catch(Exception e) {
                System.err.println(e);
            }
        }
    }

    /**
     * Esta función imprime los flags que se deben proporcionar
     * al programa para su correto funcionamiento
     */
    private static void imprimirUso(){
        String mnsjError =
            "uso: drep -p <puerto local dmon> [-v]";
        System.out.println(mnsjError);
        System.exit(1);
    }
}
